home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / extensions / samples / volspin.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  15KB  |  583 lines

  1. /*
  2.  * Copyright (c) 1995 Silicon Graphics, Inc.
  3.  * 
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee,
  6.  * provided that (i) the above copyright notices and this permission
  7.  * notice appear in all copies of the software and related documentation,
  8.  * and (ii) the name of Silicon Graphics may not be used in any
  9.  * advertising or publicity relating to the software without the specific,
  10.  * prior written permission of Silicon Graphics.
  11.  * 
  12.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  13.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  14.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  15.  * 
  16.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL,
  17.  * INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
  18.  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  19.  * OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
  20.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  21.  * OF THIS SOFTWARE.
  22.  */
  23. /*
  24.  * volspin.c - simple demo of 3D textures.
  25.  *  A 3D texture of a cube with a cubical cavity is constructed.
  26.  *  The "npolys" polygons that are parallel to the screen are displayed with
  27.  *  the texture mapped onto them.
  28.  *  To acheive rotation of the displayed volume (the cube), transformations are
  29.  *  applied to the texture coordinate by modifying the texture matrix.
  30.  *
  31.  * See usage function for options.
  32.  *
  33.  *  $Revision: 1.1 $
  34.  *
  35.  * Note: In 5.3 (and patch154) and earlier, RealityEngine has bug in the texture
  36.  *  matrix push/pop on RealityEngine, where the matrix is not properly restored
  37.  *  after pops.  This code has a workaround for this bug which is envoked when
  38.  *  #define PUSH_TEX_MAT_BUG is 1.
  39.  */
  40. #include <stdlib.h>
  41. #include <stdio.h>
  42. #include <bstring.h>
  43. #include <string.h>
  44. #include <math.h>
  45. #include <GL/glx.h>
  46. #include <GL/glu.h>
  47. #include <X11/keysym.h>
  48. #include <Xm/MwmUtil.h>
  49. #include "util.h"
  50.  
  51. #define W 600
  52. #define H 600
  53.  
  54. #if !defined(GL_EXT_texture3D) || !defined(GL_EXT_texture)
  55. Sorry either EXT_texture3D or EXT_texture is not supported by this library.
  56. #endif
  57.  
  58. #define PUSH_TEX_MAT_BUG 1
  59.  
  60. long width = W, height = H;
  61. Display *dpy;
  62. Colormap cmap;
  63. Window window;
  64. XVisualInfo *vi;
  65. GLXContext cx;
  66.  
  67. int tracking=False;
  68. int usealpha=False;
  69.  
  70. int nslices=64;
  71. int npolys=64;
  72.  
  73. int spindx = 0, spindy = 0;
  74. int startx, starty;
  75. int curx = 0, cury = 0;
  76.  
  77. void redraw(void);
  78. void drawvolume(void);
  79. void initTexMatrix(int fromInit);
  80. Window createWindow(int argc, char **argv, Bool fullScreen);
  81.  
  82. typedef struct {
  83.     GLenum param; /* name in opengl */
  84.     char *string; /* what the user types */
  85. } pair;
  86.  
  87. pair internaltab[] = {
  88.     { GL_RGBA8_EXT, "rgba8" },
  89.     { GL_RGB4_EXT, "rgb4" },
  90.     { GL_RGB5_EXT, "rgb5" },
  91.     { GL_RGB8_EXT, "rgb8" },
  92.     { GL_RGB12_EXT, "rgb12" },
  93.     { GL_RGBA4_EXT, "rgba4" },
  94.     { GL_RGBA12_EXT, "rgba12" },
  95.     { 0, NULL },
  96. };
  97.  
  98. GLenum intfmt = GL_RGBA8_EXT;
  99. char *istr = "rgba8";
  100.  
  101. #if PUSH_TEX_MAT_BUG
  102. float textureMatrix[16] = {
  103.   1, 0, 0, 0,
  104.   0, 1, 0, 0,
  105.   0, 0, 1, 0,
  106.   0, 0, 0, 1,
  107.   };
  108.  
  109. #define PUSH_TEX_MAT() glGetFloatv(GL_TEXTURE_MATRIX, textureMatrix)
  110. #define POP_TEX_MAT() glLoadMatrixf(textureMatrix)
  111. #else
  112. #define PUSH_TEX_MAT() glPushMatrix()
  113. #define POP_TEX_MAT() glPopMatrix()
  114. #endif /* def PUSH_TEX_MAT_BUG */
  115.  
  116. pair *
  117. lookuppair(pair tab[], char *name)
  118. {
  119.     int i;
  120.  
  121.     for (i=0; tab[i].param; i++) {
  122.     if (!strcmp(name, tab[i].string))
  123.             return &tab[i];
  124.     }
  125.     return NULL;
  126. }
  127.  
  128. void eventloop(void)
  129. {
  130.     XEvent event;
  131.     XButtonEvent *bev;
  132.     int x, y, size;
  133.     unsigned int w, h, bw, depth;
  134.     Window root;
  135.     
  136.     for (;;) {
  137.     if (XPending(dpy)) {
  138.         XNextEvent(dpy, &event);
  139.         bev = (XButtonEvent *) &event;
  140.         switch (event.type) {
  141.           case KeyPress:
  142.         {
  143.             char buf[100];
  144.             int rv;
  145.             KeySym ks;
  146.  
  147.             rv = XLookupString(&event.xkey, buf, sizeof(buf), &ks, 0);
  148.             switch (ks) {
  149.               case XK_Escape:
  150.             exit(EXIT_SUCCESS);
  151.             break;
  152.                       case XK_Home:
  153.                         initTexMatrix(False);
  154.                         spindx = spindy = 0;
  155.                         redraw();
  156.                         break;
  157.                       case XK_h:
  158.                       case XK_question:
  159.                         printf("Keys:\tHome - reset xform\n\tEsc - quit\n");
  160.                         printf("To move the object press a mouse button\
  161.  and move the mouse\n");
  162.                         break;
  163.             }
  164.             if (!XPending(dpy)) redraw();
  165.         }
  166.         break;
  167.           case Expose:
  168.         XGetGeometry(dpy, window, &root, &x, &y, &w, &h, &bw, &depth);
  169.         width = w;
  170.         height = h;
  171.         size = (width < height ? width : height);
  172.         glViewport((width-size)/2, (height-size)/2, size, size);
  173.         redraw();
  174.         break;
  175.           case ConfigureNotify:
  176.         width = event.xconfigure.width;
  177.         height = event.xconfigure.height;
  178.         size = (width < height ? width : height);
  179.         glViewport((width-size)/2, (height-size)/2, size, size);
  180.         redraw();
  181.         break;
  182.           case ButtonPress:
  183.         curx = startx = bev->x;
  184.         cury = starty = bev->y;
  185.         spindx = 0;
  186.         spindy = 0;
  187.         tracking = True;
  188.         break;
  189.           case ButtonRelease:
  190.         /*
  191.          * If user released the button while moving the mouse, keep
  192.          * spinning.
  193.          */
  194.         if (bev->x != curx || bev->y != cury) {
  195.             spindx = bev->x - curx;
  196.             spindy = bev->y - cury;
  197.         }
  198.         tracking = False;
  199.         break;
  200.           case MotionNotify:
  201.         if (XPending(dpy)) break;
  202.         curx = bev->x;
  203.         cury = bev->y;
  204.         if (curx != startx || cury != starty) {
  205.             redraw();
  206.             startx = curx;
  207.             starty = cury;
  208.         }
  209.         break;
  210.         }
  211.     } else {
  212.         if (!tracking && (spindx!=0 || spindy!=0)) {
  213.         redraw();
  214.         }
  215.     }
  216.     }
  217. }
  218.  
  219. #define    IMAGEXSIZE 64
  220. #define IMAGEYSIZE 64
  221. #define IMAGEZSIZE 256 
  222.  
  223.  
  224. void
  225. makeimage(int xsize, int ysize, char red, char green, char blue)
  226. {
  227.     int i, j, k;
  228.     float s, t, r, ds, dt, dr;
  229.     unsigned char *p, *buf;
  230.  
  231.     buf = (unsigned char *) malloc(xsize * ysize * nslices * 4);
  232.     ds = (xsize > 1 ? 1.0/(xsize-1) : 0);
  233.     dt = (ysize > 1 ? 1.0/(ysize-1) : 0);
  234.     dr = (nslices > 1 ? 1.0/(nslices-1) : 0);
  235.     
  236.     for (i = 0; i < nslices; i++) {
  237.     r = i*dr;
  238.     for (j = 0; j < ysize; j++) {
  239.         t = j*dt;
  240.         for (k = 0; k < xsize; k++) {
  241.         s = k*ds;
  242.         if (usealpha) {
  243.            p = &buf[(i*xsize*ysize + j*xsize + k)*4];
  244.         } else {
  245.            p = &buf[(i*xsize*ysize + j*xsize + k)*3];
  246.         }
  247.         if (!(s > .23 && s < .76 &&
  248.               t > .23 && t < .76 &&
  249.               r > .23 && r < .76) &&
  250.             !((s < .05 || s > .95) || 
  251.               (t < .05 || t > .95) || 
  252.               (r < .05 || r > .95))) {
  253.             p[0] = red;
  254.             p[1] = green;
  255.             p[2] = blue;
  256.         } else {
  257.             p[0] = p[1] = p[2] = 0x00;
  258.         }
  259.         if (usealpha) {
  260.             p[3] = 256/nslices;
  261.         }
  262.         }
  263.     }
  264.     }
  265.     printf( "downloading texture..."); fflush(stdout);
  266.     if (usealpha) {
  267.     glTexImage3DEXT(GL_TEXTURE_3D_EXT, 0, intfmt, xsize, ysize, nslices,
  268.             0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
  269.     } else {
  270.     glTexImage3DEXT(GL_TEXTURE_3D_EXT, 0, intfmt, xsize, ysize, nslices,
  271.             0, GL_RGB, GL_UNSIGNED_BYTE, buf);
  272.     }
  273.     printf( ".. done\n");
  274. }
  275.  
  276. void init(int argc, char **argv, int fullScreen)
  277. {
  278.     int i;
  279.  
  280.     window = createWindow(argc, argv, fullScreen );
  281.     cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
  282.     if (!glXMakeCurrent(dpy, window, cx)) {
  283.     fprintf(stderr, "Can't make window current to context\n");
  284.     exit(EXIT_FAILURE);
  285.     }
  286.     if (!getExtension("GL_EXT_texture3D") || !getExtension("GL_EXT_texture")) {
  287.         fprintf(stderr, "Sorry, renderer does not support either EXT_texture3D or\
  288.  EXT_texture extensions.\n");
  289.         exit(EXIT_FAILURE);
  290.     }
  291.     makeimage(IMAGEXSIZE,IMAGEYSIZE,0xff,0xff,0xff);
  292.  
  293.     glMatrixMode(GL_PROJECTION);
  294.     glLoadIdentity();
  295.     gluPerspective( 90.0, 1.0, 2.0, 20.0 );
  296.     glMatrixMode(GL_MODELVIEW);
  297.     glLoadIdentity();
  298.     initTexMatrix(True);
  299.  
  300.     glEnable(GL_AUTO_NORMAL);
  301.  
  302.     glEnable(GL_BLEND);
  303.     glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  304.     glClearColor(0.05,0.05,0.3,1.0);
  305.  
  306.     glEnable(GL_TEXTURE_3D_EXT);
  307.     glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  308.     glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  309.     glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP);
  310.     glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP);
  311.     glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_R_EXT, GL_CLAMP);
  312.     if (usealpha) {
  313.     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  314.     } else {
  315.     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  316.     }
  317. }
  318.  
  319. void drawvolume(void)
  320. {
  321.     int i;
  322.     float du, u;
  323.  
  324.     if (npolys > 1) {
  325.     du = 1.0 / (npolys-1);
  326.     } else {
  327.     du = 0.0;
  328.     }
  329.     glLoadIdentity();
  330.     glTranslatef(0.0,0.0,-10.0);
  331.     glNormal3f(0,0,-1);
  332.     glScalef(12, 12, 12);
  333.     glTranslatef(-.5,-.5,-.5);
  334.     if (usealpha) {
  335.     glColor4f(1, 1, 1, 1);
  336.     } else {
  337.     glColor4f(1,0.5,0.5,du * 1.3);
  338.     }
  339.  
  340.     for (i=0; i < npolys; i++) {
  341.     u = i*du;
  342.     glBegin(GL_POLYGON);
  343.         glTexCoord3f(0, 0, 2*u); glVertex3f( 0, 0, u);
  344.         glTexCoord3f(2, 0, 2*u); glVertex3f( 1, 0, u);
  345.         glTexCoord3f(2, 2, 2*u); glVertex3f( 1, 1, u);
  346.         glTexCoord3f(0, 2, 2*u); glVertex3f( 0, 1, u);
  347.     glEnd();
  348.     }
  349. }
  350.  
  351. void initTexMatrix(int fromInit)
  352. {
  353. #if PUSH_TEX_MAT_BUG
  354.     int i;
  355.  
  356.     bzero(textureMatrix, sizeof(textureMatrix));
  357.     for (i = 0; i < 4; i++)
  358.         textureMatrix[4*i + i] = 1;
  359. #endif
  360.     glMatrixMode(GL_TEXTURE);
  361.     if (!fromInit)
  362.       POP_TEX_MAT();
  363.     glLoadIdentity();
  364.     glScalef(.87,.87,.87);
  365.     glTranslatef(.5,.5,.5);
  366.     PUSH_TEX_MAT();
  367.     glMatrixMode(GL_MODELVIEW);
  368. }
  369.  
  370. void redraw(void)
  371. {
  372.     float dx, dy;
  373.     float len;
  374.     static GLuint vcount;
  375.  
  376.     glClear(GL_COLOR_BUFFER_BIT);
  377.     
  378.     glMatrixMode(GL_TEXTURE);
  379.     POP_TEX_MAT();
  380.  
  381.     if (tracking) {
  382.     dx = curx - startx;
  383.     dy = cury - starty;
  384.     } else {
  385.     dx = spindx;
  386.     dy = spindy;
  387.     }
  388.     if (dx || dy) {
  389.         len = sqrt(dx * dx + dy * dy);
  390.         dx /= len;
  391.         dy /= len;
  392.  
  393.     glRotatef(-0.5 * len, dy, dx, 0);
  394.     }
  395.     PUSH_TEX_MAT();
  396.  
  397.     glTranslatef(-1,-1,-1);
  398.     glMatrixMode(GL_MODELVIEW);
  399.  
  400.     drawvolume();
  401.     glXSwapBuffers(dpy, window);
  402. }
  403.  
  404. static void usage(char *name, int exitStatus)
  405. {
  406.     int i, len;
  407.     
  408.     fprintf(stderr, "usage: %s [-f (full screen)] [-s #slices] [-p #polys]\
  409.  [-a(utospin)]\n", name);
  410.     fprintf(stderr,
  411.             "\t[-A (use alpha channel)] [-i `internal texture format'] [-h(elp)]\n");
  412.     fprintf(stderr, "\tInternal formats: ");
  413.     len = strlen("Internal formats: ");
  414.     for (i = 0; internaltab[i].param; i++) {
  415.         len += strlen(internaltab[i].string) + 2;
  416.     fprintf(stderr, "%s%s", internaltab[i].string,
  417.                 internaltab[i + 1].param == 0 ? "\n" : (len > 65 ? "\n\t\t" : ", "));
  418.         if (len > 65)
  419.           len = 0;
  420.     }
  421.     fprintf(stderr,
  422.             "\tInteractively, `h/?' keys provide description of interface\n");
  423.     exit(exitStatus);
  424. }
  425.  
  426.  
  427. int main(int argc, char **argv)
  428. {
  429.     int i;
  430.     int fullScreen=0;
  431.     pair *pp;
  432.  
  433.     for (i=1; i<argc; i++) {
  434.     if (argv[i][0] == '-') {
  435.         switch (argv[i][1]) {
  436.           case 's':
  437.                 i++;
  438.         if (i > argc) {
  439.                     fprintf(stderr, "Missing argument for `-s' option\n");
  440.                     usage(argv[0], EXIT_FAILURE);
  441.                 }
  442.         nslices = atoi(argv[i]);
  443.         break;
  444.           case 'p':
  445.                 i++;
  446.         if (i >= argc) {
  447.                     fprintf(stderr, "Missing argument for `-p' option\n");
  448.                     usage(argv[0], EXIT_FAILURE);
  449.                 }
  450.         npolys = atoi(argv[i]);
  451.         break;
  452.           case 'f':
  453.         fullScreen = True;
  454.         break;
  455.           case 'a':
  456.                 spindx = spindy = 20;
  457.         break;
  458.           case 'A':
  459.         usealpha = True;
  460.         break;
  461.           case 'i':
  462.         i++;
  463.         if (i >= argc) {
  464.                     fprintf(stderr, "Missing argument for `-i' option\n");
  465.                     usage(argv[0], EXIT_FAILURE);
  466.                 }
  467.         pp = lookuppair(internaltab, argv[i]);
  468.         if (pp == NULL) {
  469.             fprintf(stderr, "Unreconized internal format argument (`%s')\
  470.  for `-i' option\n", argv[i]);
  471.             exit(EXIT_FAILURE);
  472.         }
  473.         intfmt = pp->param;
  474.         istr = pp->string;
  475.         break;
  476.               case 'h':
  477.         usage(argv[0], EXIT_SUCCESS);
  478.                 /* usage never returnes */
  479.           default:
  480.                 fprintf(stderr, "Bad option `%s'\n", argv[i]);
  481.         usage(argv[0], EXIT_FAILURE);
  482.         }
  483.     } else {
  484.             fprintf(stderr, "Bad option `%s'\n", argv[i]);
  485.         usage(argv[0], EXIT_FAILURE);
  486.     }
  487.     }
  488.  
  489.     init(argc, argv, fullScreen);
  490.     printf("using internal format: %-6s\n", istr);
  491.  
  492.     eventloop();
  493.     glXMakeCurrent(dpy, None, NULL);
  494.     glXDestroyContext(dpy, cx);
  495.     XCloseDisplay(dpy);
  496. }
  497.  
  498. /****************************************************************************/
  499.  
  500. /*
  501.  * Create an X window.
  502.  */
  503.  
  504. static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
  505. {
  506.     if ((e->type == MapNotify) && (e->xmap.window == (Window)arg)) {
  507.     return GL_TRUE;
  508.     }
  509.     return GL_FALSE;
  510. }
  511.  
  512. Window createWindow( int argc, char **argv, Bool fullScreen )
  513. {
  514.     Window window;
  515.     XSetWindowAttributes swa;
  516.     XSizeHints sh;
  517.     XEvent event;
  518.     int attributes[] = {
  519.         GLX_RGBA,
  520.         GLX_DOUBLEBUFFER,
  521.         GLX_RED_SIZE, 1,
  522.         GLX_GREEN_SIZE, 1,
  523.         GLX_BLUE_SIZE, 1,
  524.         GLX_ALPHA_SIZE, 1,
  525.         None,
  526.     };
  527.  
  528.  
  529.     dpy = XOpenDisplay(0);
  530.     if (!dpy) {
  531.     fprintf(stderr, "Can't connect to display \"%s\"\n",
  532.         getenv("DISPLAY"));
  533.     exit(EXIT_FAILURE);
  534.     }
  535.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributes);
  536.     if (!vi) {
  537.         fprintf(stderr, "Cannot find required visual on \"%s\"\n",
  538.                 getenv("DISPLAY"));
  539.         exit(EXIT_FAILURE);
  540.     }
  541.  
  542.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual,
  543.                AllocNone);
  544.     swa.background_pixel = 0;
  545.     swa.border_pixel = 0;
  546.     swa.colormap = cmap;
  547.     swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask |
  548.         KeyReleaseMask | ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
  549.  
  550.     if (fullScreen) {
  551.     width = DisplayWidth( dpy, 0 );
  552.     height = DisplayHeight( dpy, 0 );
  553.     sh.x = 0;
  554.     sh.y = 0;
  555.     } else {
  556.     sh.x = 50;
  557.     sh.y = 50;
  558.     }
  559.     sh.flags = USPosition | PPosition;
  560.     window = XCreateWindow(dpy, RootWindow(dpy, vi->screen), sh.x, sh.y,
  561.                width, height,
  562.                0, vi->depth, InputOutput, vi->visual,
  563.                CWBorderPixel|CWColormap|CWEventMask|CWBackPixel,
  564.                &swa);
  565.     XSetStandardProperties(dpy, window, argv[0], argv[0],
  566.                None, argv, argc, &sh);
  567.     XSetWMColormapWindows(dpy, window, &window, 1);
  568.     if (fullScreen) {
  569.     /* turn off window decorations */
  570.     Atom hints_atom;
  571.     MotifWmHints hints;
  572.  
  573.     hints_atom = XInternAtom( dpy, "_MOTIF_WM_HINTS", 0 );
  574.     hints.flags = MWM_HINTS_DECORATIONS;
  575.     hints.decorations = 0;
  576.     XChangeProperty( dpy, window, hints_atom, hints_atom, 32,
  577.              PropModeReplace, (unsigned char*)&hints, 5 );
  578.     }
  579.     XMapWindow(dpy, window);
  580.     XIfEvent(dpy, &event, WaitForMapNotify, (char*)window);
  581.     return window;
  582. }
  583.